package dao

import (
	"chat/app/common"
	"chat/utils"
	"context"
	"errors"
	"fmt"
	"github.com/go-redis/redis/v8"
	"time"
)

// 文档 https://github.com/go-redis/redis

var ctx = context.Background()

// SetEX 存值
func SetEX(key string, value any, expiration time.Duration) error {
	if key == "" || value == nil {
		return errors.New(common.GetMsg(common.INVALID_PARAMS))
	}
	rdb := utils.GetRedis()
	err := rdb.SetEX(ctx, key, value, expiration).Err()
	if err != nil {
		return errors.New(err.Error())
	}
	return nil
}

// SetString 存值
func SetString(key string, value any, exps ...time.Duration) error {
	if key == "" || value == nil {
		return errors.New(common.GetMsg(common.INVALID_PARAMS))
	}
	var expiration time.Duration
	expiration = 0
	for _, exp := range exps {
		expiration = exp // 过期时间
		break
	}
	rdb := utils.GetRedis()
	err := rdb.Set(ctx, key, value, expiration).Err()
	if err != nil {
		return errors.New(err.Error())
	}
	//log.Printf("push key: %v, value: %v", key, value)
	return nil
}

// GetString 取值
func GetString(key string) (string, error) {
	if key == "" {
		return "", errors.New(common.GetMsg(common.INVALID_PARAMS))
	}
	rdb := utils.GetRedis()
	res, err := rdb.Get(ctx, key).Result()
	if err == redis.Nil {
		return "", errors.New(fmt.Sprintf(common.GetMsg(common.INVALID_RESULT), key))
	}
	if err != nil {
		return "", errors.New(err.Error())
	}
	return res, nil
}

// Del 删除字段
func Del(keys ...string) error {
	if len(keys) <= 0 {
		return errors.New("无效的参数")
	}
	rdb := utils.GetRedis()
	err := rdb.Del(ctx, keys...).Err()
	if err != nil {
		return errors.New(err.Error())
	}
	return nil
}

// Expire 设置ttl
func Expire(key string, exp time.Duration) error {
	if key == "" {
		return errors.New("无效的参数")
	}
	rdb := utils.GetRedis()
	err := rdb.Expire(ctx, key, exp).Err()
	if err != nil {
		return errors.New(err.Error())
	}
	return nil
}

// RPush 右侧push数据
func RPush(key string, values ...any) error {
	if key == "" {
		return errors.New("无效的参数")
	}
	rdb := utils.GetRedis()
	err := rdb.RPush(ctx, key, values...).Err()
	if err != nil {
		return errors.New(err.Error())
	}
	return nil
}

// LLen 列表数量
func LLen(key string) (int64, error) {
	if key == "" {
		return 0, errors.New("无效的参数")
	}
	rdb := utils.GetRedis()
	count, err := rdb.LLen(ctx, key).Result()
	if err != nil {
		return 0, errors.New(err.Error())
	}
	return count, nil
}

// LPop 移除并返回列表的第一个元素
func LPop(key string) (string, error) {
	if key == "" {
		return "", errors.New("无效的参数")
	}
	rdb := utils.GetRedis()
	res, err := rdb.LPop(ctx, key).Result()
	if err != nil {
		return "", errors.New(err.Error())
	}
	return res, nil
}

// BLPop 移除并返回列表的第一个元素，如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
func BLPop(key string, timeout time.Duration) (string, error) {
	if key == "" {
		return "", errors.New("无效的参数")
	}
	rdb := utils.GetRedis()
	res, err := rdb.BLPop(ctx, timeout, key).Result()
	if err != nil {
		return "", errors.New(err.Error())
	}
	var val string
	if res != nil {
		val = res[1]
	}
	return val, nil
}
